﻿using System;
using System.Configuration;
using System.IO;
using System.Reflection;
using EPiServer;
using EPiServer.BaseLibrary;
using EPiServer.Configuration;
using EPiServer.DataAccess;
using EPiServer.Framework.Initialization;
using EPiServer.Web.Hosting;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace SearchAndReplaceUnitTests.Environment
{

    public static class EPiServerInitializer
    {

        /// <summary>
        /// Initializes EPiServer
        /// </summary>
        /// <param name="context">The test context for which EPiServer is initialized</param>
        public static void Initialize(TestContext context)
        {
            // Initialize settings from App.config
            try
            {
                Settings.InitializeAllSettings(ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None));
            }
            catch (ConfigurationErrorsException ex)
            {
                throw new Exception("The application configuration file does not seem to contain required EPiServer configuration");
            }

            // Map host settings
            try
            {
                SiteMappingConfiguration.Instance = new SiteMappingConfiguration();
                Settings.Instance = Settings.MapHostToSettings("*", true);
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to map host settings", ex);
            }

            // Initialize ClassFactory
            try
            {
                ClassFactory.Instance = new EPiServer.Implementation.DefaultBaseLibraryFactory(String.Empty);
                ClassFactory.RegisterClass(typeof(IRuntimeCache), typeof(EPiServer.Implementation.DefaultRuntimeCache));
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to initialize ClassFactory", ex);
            }

            // Initialize hosting environment
            try
            {
                // Use a custom hosting environment designed to run without a web context
                GenericHostingEnvironment.Instance = new EPiServerHostingEnvironment();
            }
            catch (Exception ex)
            {
                throw new Exception("Could not initialize VPP", ex);
            }

            // Configure Global settings
            try
            {
                Global.BaseDirectory = context.TestDeploymentDir;
                Global.InstanceName = "EPiServer Unit Test";
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to configure Global class", ex);
            }

            // Configure data access
            try
            {
                DataAccessBase.Initialize(ConfigurationManager.ConnectionStrings[Settings.Instance.ConnectionStringName],
                    TimeSpan.Zero, 0, TimeSpan.Zero);
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to set up database access", ex);
            }

            // Copy embedded language file to test deployment directory
            try
            {
                // Create lang folder
                var langFolder = Directory.CreateDirectory(Global.BaseDirectory).CreateSubdirectory("lang");

                // Create a language file based on the embedded resource
                using (var langFile = File.CreateText(langFolder.FullName + "\\lang_EN.xml"))
                {
                    string xml = string.Empty;

                    using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("SearchAndReplaceUnitTests.EmbeddedResources.lang_EN.xml"))
                    {
                        using (StreamReader streamReader = new StreamReader(stream))
                        {
                            xml = streamReader.ReadToEnd();
                        }
                    }

                    langFile.Write(xml);
                    langFile.Close();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to copy language file to test deployment directory", ex);
            }

            // Copy embedded language file to test deployment directory
            try
            {
                // Create lang folder
                var langFolder = Directory.CreateDirectory(context.TestDeploymentDir).CreateSubdirectory("lang");

                // Create a language file based on the embedded resource
                using (var langFile = File.CreateText(langFolder.FullName + "\\lang_EN.xml"))
                {
                    string xml = string.Empty;

                    using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("SearchAndReplaceUnitTests.EmbeddedResources.lang_EN.xml"))
                    {
                        using (StreamReader streamReader = new StreamReader(stream))
                        {
                            xml = streamReader.ReadToEnd();
                        }
                    }

                    langFile.Write(xml);
                    langFile.Close();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to copy language file to test deployment directory", ex);
            }

            // Copy license.config to test deployment directory
            try
            {
                var outputDirectory = Directory.CreateDirectory(Global.BaseDirectory);

                // Create a language file based on the embedded resource
                using (var licenseConfig = File.CreateText(outputDirectory.FullName + "\\License.config"))
                {
                    string xml = string.Empty;

                    using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("SearchAndReplaceUnitTests.EmbeddedResources.License.config"))
                    {
                        using (StreamReader streamReader = new StreamReader(stream))
                        {
                            xml = streamReader.ReadToEnd();
                        }
                    }

                    licenseConfig.Write(xml);
                    licenseConfig.Close();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to copy the license.config to test deployment directory", ex);
            }

            // Copy embedded license.config to test deployment directory
            try
            {
                // Create lang folder
                var langFolder = Directory.CreateDirectory(context.TestDeploymentDir);

                // Create a language file based on the embedded resource
                using (var licenseConfig = File.CreateText(langFolder.FullName + "\\License.config"))
                {
                    string xml = string.Empty;

                    using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("SearchAndReplaceUnitTests.EmbeddedResources.License.config"))
                    {
                        using (StreamReader streamReader = new StreamReader(stream))
                        {
                            xml = streamReader.ReadToEnd();
                        }
                    }

                    licenseConfig.Write(xml);
                    licenseConfig.Close();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Unable to copy the license.config to test deployment directory", ex);
            }

            // Start EPiServer initialization
            try
            {
                InitializationModule.FrameworkInitialization(HostType.Service);
            }
            catch (Exception ex)
            {
                throw new Exception("EPiServer framework could not be initialized", ex);
            }
        }

    }

}